using System;
using System.Linq;
using Uber.Core.Model;
using Uber.Core.Repository;
using Uber.Core.Service;
using Uber.Data;

namespace Uber.Service
{
    public static class Aaa
    {
        public static void SetMail(this Notification n, Account o, bool onAnswer = false)
        {
            if (onAnswer)
            {
                if (o.MailOnAnswer && o.HasMail)
                {
                    n.SendEmail = true;
                    n.Email = o.Mail;
                }
            }
            else if (o.MailOnComment && o.HasMail)
            {
                n.SendEmail = true;
                n.Email = o.Mail;
            }
        }
    }

    public class Notifications : INotifications
    {
        private readonly IRepo<Notification> repo;
        private readonly IUniRepo uni;
        private IURepo u;

        public Notifications(IRepo<Notification> repo, IUniRepo uni, IURepo u)
        {
            this.repo = repo;
            this.uni = uni;
            this.u = u;
        }

        public void NewAnswerAdded(long postId, long who, long answerId)
        {
            var post = uni.Get<Post>(postId);
            if (who == post.OwnerId) return;
            var o = new Notification { PostId = postId, AccountId = post.OwnerId, Date = DateTime.Now, CauseId = answerId };
            o.SetMail(post.Owner, true);

            repo.Add(o);
            repo.Save();
        }

        public void NewCommentAdded(long postId, long who, string comment, long commentId)
        {
            var post = uni.Get<Post>(postId);
            if (post.OwnerId != who)
            {
                var o = new Notification { PostId = postId, AccountId = post.OwnerId, Date = DateTime.Now, NType = 1, CauseId = commentId };
                o.SetMail(post.Owner);
                repo.Add(o);
            }
            if (comment.Contains("@"))
            {
                var owners = post.Comments.Where(c => c.OwnerId != who).Select(o => o.Owner).Distinct().ToList();
                foreach (var o in owners.Where(n => comment.Contains("@" + n.DisplayName)))
                {
                    var n = new Notification { PostId = postId, AccountId = o.Id, Date = DateTime.Now, NType = 2, CauseId = commentId };
                    n.SetMail(o);
                    repo.Add(n);
                }
            }
            repo.Save();
        }

        public void CommentEdited(long postId, long commentId, string comment, string oldcomment, long who)
        {
            var post = uni.Get<Post>(postId);
            var owners = post.Comments.Select(o => o.Owner).Where(o => o.Id != who).Distinct();

            foreach (var o in owners)
            {
                if (oldcomment.Contains("@" + o.DisplayName) && !comment.Contains("@" + o.DisplayName))
                {
                    var o1 = o;
                    foreach (var x in repo.Where(c => c.CauseId == commentId && c.AccountId == o1.Id))
                        repo.Remove(x);
                }

                if (!oldcomment.Contains("@" + o.DisplayName) && comment.Contains("@" + o.DisplayName))
                {
                    var n = new Notification
                                {
                                    PostId = postId,
                                    AccountId = o.Id,
                                    Date = DateTime.Now,
                                    NType = 2,
                                    CauseId = commentId
                                };
                    n.SetMail(o);
                    uni.Add(n);
                }
            }
            repo.Save();
        }

        public void CommentDeleted(long commentId)
        {
            foreach (var o in repo.Where(o => o.CauseId == commentId))
                repo.Remove(o);
            repo.Save();
        }

        public void Read(long nid)
        {
            var o = repo.Get(nid);
            o.IsRead = true;
            repo.Save();
        }

        public void ReadAll(long userId)
        {
            u.UpdateWhatWhere<Notification>(new { IsRead = true }, new { AccountId = userId });
        }

        public void DeleteAll(long userId)
        {
            u.DeleteWhere<Notification>(new{AccountId = userId});
        }
    }
}